#include "SignedRequestCore.hpp"

using namespace BFT::messages;

/**
constructor that accepts specific message fields. This
constructor builds the message bytes representation
starting from where VerifiedMessageBase leaves off
**/
SignedRequestCore::SignedRequestCore(uint32_t _clientId, uint32_t _requestId, boost::shared_ptr<char> _command, uint32_t _command_size)
	: SignedMessage::SignedMessage(tag(),Entry::computeSize(_command_size), _clientId)
{
//	requestId = _requestId;
//	command = _command;
//	command_size = _command_size;
//	
//	int offset = getOffset();
	
	entry.reset( new Entry(_clientId, _requestId, command, command_size));
	
	int bytes_size;
	boost::shared_ptr<char> bytes = VerifiedMessageBase::getBytes(bytes_size);
	
	int entry_bytes_size;
	boost::shared_ptr<char> entry_bytes = entry.get()->getBytes(entry_bytes_size);

	int offset = getOffset();	
	memcpy((void*)(bytes.get()+offset), (const void*)(entry_bytes.get()), entry_bytes_size );	
	
//	*(uint32_t*)(buffer.get()+offset) = htonl(requestId); //setting requestId
//	offset += REQUEST_ID_SIZE;
//	
//	*(uint32_t*)(buffer.get()+offset) = htonl(command_size); //setting command size
//	offset += COMMAND_SIZE_SIZE;
//	
//	memcpy( (void*)(buffer.get()+offset) , (const void*)(command.get()) , command_size); // setting the command
//	//fprintf(stdout,"end of signedrequestcore constructor\n");
//	sign();
}

/**
Constructor that accepts a byte represnetation of the message.
Parses the byte representation to populate the class fields.
**/
SignedRequestCore::SignedRequestCore(boost::shared_ptr<char> _buffer, uint32_t _buffer_size)
	: SignedMessage(_buffer, _buffer_size)
{
//	fprintf(stdout,"req constructor has been called. buffer_length:%d\n",_buffer_size);
//	VerifiedMessageBase::printInfo();
	if( VerifiedMessageBase::getTag() != SIGNED_REQUEST_CORE ) //accessing verifiedmessagebase's getTag through SignedMessage
	{
		fprintf(stderr,"unable to construct signedrequestcore from bytes: invalid tag %d/n",SignedMessage::getTag());
		exit(15);
	}
	
	uint32_t offset = getOffset();

	entry = Entry::fromBytes(_buffer, _buffer_size, offset);
	
	offset += entry.get()->getSize();
//	
//	requestId = ntohl(*(uint32_t*)(_buffer.get()+offset)); //parsing requestId
//	offset += REQUEST_ID_SIZE;
//	
//	command_size = ntohl(*(uint32_t*)(_buffer.get()+offset)); //parsing command_size
//	offset += COMMAND_SIZE_SIZE;
//	
//	command.reset((char*)malloc(command_size), free);
//	
//	memcpy( (void*)(command.get()) , (const void*)(_buffer.get()+offset) , command_size); //parsing command
//	offset += command_size;

	if (offset != buffer_length - getAuthenticationSize())
	{
		fprintf(stderr,"unable to construct signedrequestcore from bytes, invalid bytes\n");
		fprintf(stdout,"offset:%d requestid:%d, command_size:%d, command:%s\n",getOffset(), requestId, command_size, command.get());
		exit(16);
	}
	
	//fprintf(stdout,"built signedrequestcore. offset:%d requestid:%d, command_size:%d, command:%s\n",getOffset(), requestId, command_size, command.get());
} 	

SignedRequestCore::SignedRequestCore(boost::shared_ptr<Entry> _entry)
	:SignedMessage::SignedMessage(tag(), computeSize(_entry), _entry.get()->getClient())
{
	entry = _entry;
	
	int bytes_size;
	boost::shared_ptr<char> bytes = VerifiedMessageBase::getBytes(bytes_size);
	
	int entry_bytes_size;
	boost::shared_ptr<char> entry_bytes = entry.get()->getBytes(entry_bytes_size);

	int offset = getOffset();	
	memcpy((void*)(bytes.get()+offset), (const void*)(entry_bytes.get()), entry_bytes_size );
} 

//boost::shared_ptr<Entry> SignedRequestCore::getEntry()
//{
//	boost::shared_ptr<Entry> entry(new Entry(getSendingClient(), requestId, command, command_size) );
//	return entry;
//}

bool SignedRequestCore::equals(boost::shared_ptr<RequestCore> _other_rc)
{
	boost::shared_ptr<SignedRequestCore> _other_src = boost::dynamic_pointer_cast<SignedRequestCore>(_other_rc);
	
	if (!SignedMessage::equals(_other_src) || requestId!=_other_src.get()->getRequestId())
		return false;

	return entry.get()->equals(_other_src.get()->getEntry());		
//	bool different=false;	
//	
//	for(uint32_t i=0; i<command_size; i++)
//	{
//		different = different || (command.get()[i] == _other_src.get()->getCommand().get()[i]);
//	}
//	return !different;
}

void SignedRequestCore::printInfo()
{
	SignedMessage::printInfo();
	fprintf(stdout,"SignedRequestCore information:\n");
	entry.get()->printInfo();
//	fprintf(stdout,"Size of the request:\t%d\n", computeSize(command_size));
//	fprintf(stdout,"Request ID:\t%d\n",requestId);
//	fprintf(stdout,"Command size:\t%d\n",command_size);
//	
//	fprintf(stdout,"Command: \t");
//	for (uint32_t i=0; i<command_size; i++)
//		fprintf(stdout,"|%02X",command.get()[i]);
//	fprintf(stdout,"\n");	
	
}

boost::shared_ptr<char> SignedRequestCore::getBytes(int& _bytes_length)
{

	return SignedMessage::getBytes(_bytes_length);
}

uint32_t SignedRequestCore::getTotalSize()
{
	return SignedMessage::getTotalSize();
}

uint16_t SignedRequestCore::getTag()
{
	return SignedMessage::getTag();
}

